/*
* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* openUBMC is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*         http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

#include <gtest/gtest.h>
#include <test_utilities/test_base.h>

#include "drivers/pcie_gpu_card/innosilicon/awm_m11p/awm_m11p_gpu.h"
#include <mc/engine.h>
#include <mc/common.h>

namespace drivers {
namespace pcie_gpu_card {
namespace innosilicon {
namespace awm_m11p_test {

class awm_m11p_test_service : public mc::engine::service {
public:
    awm_m11p_test_service(const std::string& name) : mc::engine::service(name) {}
};

// ========================= awm_m11p_gpu测试 =========================
class AwmM11pGpuTest : public mc::test::TestWithEngine {
protected:
    static void SetUpTestSuite() {
        TestWithEngine::SetUpTestSuite();
        m_test_service = std::make_unique<awm_m11p_test_service>("bmc.openubmc.test_awm_m11p_gpu");
        m_test_service->init();
        m_test_service->start();
    }
    static void TearDownTestSuite() {
        m_test_service->stop();
        TestWithEngine::TearDownTestSuite();
    }
    void SetUp() override {}
    void TearDown() override {}
    static std::unique_ptr<awm_m11p_test_service> m_test_service;
};
std::unique_ptr<awm_m11p_test_service> AwmM11pGpuTest::m_test_service;

// 基本 start/stop
TEST_F(AwmM11pGpuTest, basic_start_stop) {
    dev::awm_m11p_gpu gpu;
    EXPECT_TRUE(gpu.start());
    EXPECT_TRUE(gpu.stop());
}
// 构造函数默认
TEST_F(AwmM11pGpuTest, default_constructor) {
    dev::awm_m11p_gpu gpu;
    EXPECT_FALSE(gpu.m_processor.Presence);
    EXPECT_EQ(gpu.m_gpu.Utilization, 0);
    EXPECT_EQ(gpu.m_gpu.TemperatureCelsius, 0);
}
// init 空配置
TEST_F(AwmM11pGpuTest, init_empty_config) {
    dev::awm_m11p_gpu gpu;
    gpu.set_service(m_test_service.get());
    mc::mutable_dict config;
    mc::dict connector;
    EXPECT_TRUE(gpu.init(config, connector));
}
// init 含成员配置
TEST_F(AwmM11pGpuTest, init_with_properties) {
    dev::awm_m11p_gpu gpu;
    gpu.set_service(m_test_service.get());
    mc::mutable_dict config;
    config["bmc.dev.Processor"] = mc::dict{{"Presence", true}};
    config["bmc.dev.Gpu"] = mc::dict{{"Utilization", 50}, {"TemperatureCelsius", 75}};
    config["bmc.dev.Gpu.Power"] = mc::dict{{"PowerWatts", 150}};
    config["bmc.dev.Gpu.Status"] = mc::dict{{"ECCModeEnabled", 1}};
    mc::dict connector;
    EXPECT_TRUE(gpu.init(config, connector));
}
// reset_default_properties 覆盖全部字段
TEST_F(AwmM11pGpuTest, reset_default_properties_all) {
    dev::awm_m11p_gpu gpu;
    ASSERT_TRUE(gpu.reset_default_properties());
    EXPECT_FALSE(gpu.m_processor.Presence);
    EXPECT_EQ(gpu.m_gpu.InfoRomVersion, std::string());
    EXPECT_EQ(gpu.m_gpu.BuildDate, std::string());
    EXPECT_EQ(gpu.m_gpu.UUID, std::string());
    EXPECT_EQ(gpu.m_gpu.Utilization, 0);
    EXPECT_EQ(gpu.m_gpu.TemperatureCelsius, 0);
    EXPECT_EQ(gpu.m_gpu_power.PowerWatts, 0);
    EXPECT_EQ(gpu.m_gpu_power.PowerBrakeState, 255);
    EXPECT_EQ(gpu.m_gpu_power.ExternalPowerSufficient, 255);
    EXPECT_EQ(gpu.m_gpu_status.ECCModeEnabled, 255);
    EXPECT_EQ(gpu.m_gpu_status.ECCModePendingEnabled, 255);
    EXPECT_EQ(gpu.m_gpu_status.ResetRequired, 255);
}
// 多次 reset_default_properties
TEST_F(AwmM11pGpuTest, multiple_reset_default_properties) {
    dev::awm_m11p_gpu gpu;
    for (int i = 0; i < 3; i++) {
        EXPECT_TRUE(gpu.reset_default_properties());
    }
}
// 多实例
TEST_F(AwmM11pGpuTest, multi_instance) {
    std::vector<std::unique_ptr<dev::awm_m11p_gpu>> gpus;
    for (int i = 0; i < 3; i++) {
        auto gpu = std::make_unique<dev::awm_m11p_gpu>();
        gpu->set_service(m_test_service.get());
        gpu->set_object_name(("gpu_" + std::to_string(i)).c_str());
        EXPECT_TRUE(gpu->start());
        gpus.push_back(std::move(gpu));
    }
}

} // namespace awm_m11p_test
} // namespace innosilicon
} // namespace pcie_gpu_card
} // namespace drivers
